package com.husk.ali;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 阿里IPV4转32进制回文笔试
 * </p>
 *
 * @author hushunke@sm.vvip-u.com
 * @since 2021/3/17
 */
public class AliJobInterview {

    /**
     * 0-9不重复
     * <p>
     * 0-255.0-255.0-255.0-255
     * <p>
     * a.b.c.d
     * <p>
     * a和d是回文，且没有重复数字，b和c是回文，且没有重复数字
     * <p>
     * 二进制是回文数
     */
    int count = 0;

    /**
     * 第一种算法，a和d算一次，b和c再算一次
     */
    public void gen() {
        for (int i = 0; i <= 255; i++) {
            // 1. 生成a和d，判断a和d有没有重复
            Integer a = i;
            // 2. 生成d (a转2进制，求a的回文)，
            Integer d = this.binaryConvert2Decimalism(new StringBuilder(this.decimalismConvert2Binary(a)).reverse().toString());

            // a和d不相等，且a和d中没有出现重复数字
            if (!a.equals(d) && !this.hasRepeatNum(a, d)) {
                // 3. 生成b和c，判断b和c有没有重复
                for (int j = 0; j <= 255; j++) {
                    Integer b = j;
                    Integer c = this.binaryConvert2Decimalism(new StringBuilder(this.decimalismConvert2Binary(b)).reverse().toString());
                    if (!this.hasRepeatNum(a, b, c, d)) {
                        String result1 = a + "." + b + "." + c + "." + d;
                        String result2 = this.decimalismConvert2Binary(a) + "." +
                                this.decimalismConvert2Binary(b) + "." +
                                this.decimalismConvert2Binary(c) + "." +
                                this.decimalismConvert2Binary(d);
                        System.out.println(result1);
                        System.out.println(result2);
                        count++;
                    }
                }
            }
        }
        System.out.println(count);
    }

    /**
     * 第二种算法，只算1次，做笛卡尔积
     */
    public void gen2() {
        List<Integer[]> pairs = new ArrayList<>();
        for (int i = 0; i <= 255; i++) {
            // 1. 生成a和d，判断a和d有没有重复
            Integer a = i;
            // 2. 生成d (a转2进制，求a的回文)，
            Integer d = this.binaryConvert2Decimalism(new StringBuilder(this.decimalismConvert2Binary(a)).reverse().toString());
            if (!a.equals(d) && !this.hasRepeatNum(a, d)) {
                pairs.add(new Integer[]{a, d});
            }
        }
        for (int i = 0; i < pairs.size(); i++) {
            for (int j = 0; j < pairs.size(); j++) {
                if (j == i) {
                    continue;
                }
                Integer[] ad = pairs.get(i);
                Integer[] bc = pairs.get(j);
                Integer a = ad[0];
                Integer b = bc[0];
                Integer c = bc[1];
                Integer d = ad[1];
                if (!this.hasRepeatNum(a, b, c, d)) {
                    String result1 = a + "." + b + "." + c + "." + d;
                    String result2 = this.decimalismConvert2Binary(a) + "." +
                            this.decimalismConvert2Binary(b) + "." +
                            this.decimalismConvert2Binary(c) + "." +
                            this.decimalismConvert2Binary(d);
                    System.out.println(result1);
                    System.out.println(result2);
                    count++;
                }
            }
        }
        System.out.println(count);
    }

    /**
     * 10进制转2进制
     *
     * @param num
     * @return
     */
    public String decimalismConvert2Binary(Integer num) {
        // 8位2进制，最大255，最小0
        if (num == null || num > 255 || num < 0) {
            throw new RuntimeException("unsupport");
        }
        StringBuilder result = new StringBuilder(Integer.toBinaryString(num));
        while (result.length() < 8) {
            result.insert(0, "0");
        }
        return result.toString();
    }

    /**
     * 2进制转10进制
     *
     * @param binary
     * @return
     */
    public Integer binaryConvert2Decimalism(String binary) {
        return Integer.parseInt(binary, 2);
    }

    /**
     * 判断是否是回文数
     *
     * @param str
     * @return
     */
    public boolean isPalindromic(String str) {
        int left = 0, right = str.length() - 1;
        while (left < right) {
            if (str.charAt(left) != str.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    /**
     * 判断传入的是否有重复数字
     *
     * @param i
     * @return false没有重复，true重复
     */
    public boolean hasRepeatNum(Integer... i) {
        // 所有数字生成字符串
        String str = Arrays.stream(i).map(Object::toString).collect(Collectors.joining());
        // 判断字符串是否有重复的字符
        Set<String> set = new HashSet<>(Arrays.asList(str.split("")));
        return set.size() != str.length();
    }

}
